package com.diao.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandler;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;

import java.util.concurrent.TimeUnit;

/**
 * @author: chenzhidiao
 * @date: 2021/4/18 11:45
 * @description:
 * @version: 1.0
 */

/**
 * 自定义一个 Handler 需要继承 Netty 规定好的某个 HandlerAdapter 适配器
 * Netty 内置了多个适配器
 * 这时我们定义的 Handler 才能称为 Handler
 */
public class NettyServerHandler extends ChannelInboundHandlerAdapter  {

    /**
     * 读取数据的方法
     * @param ctx 上下文对象，可以获取到 ChannelPipelin，Channel
     * @param msg 客户端发送的数据，默认是Object类型
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

//        System.out.println("服务器处理线程为："+ Thread.currentThread().getName());
//
//        System.out.println(" server ctx = " + ctx);
        //如果有耗时比较长的任务，为了避免阻塞，可以将该任务放到EventLoop的taskQueue任务队列中异步执行
        ctx.channel().eventLoop().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(10*1000);

                    System.out.println("111");
                }catch (Exception e){
                    System.out.println("发生异常"+ e.getMessage());
                }
            }
        });

        //自定义定时任务
        ctx.channel().eventLoop().schedule(new Runnable() {
            @Override
            public void run() {
                try{
                    Thread.sleep(5*1000);
                    //ctx.writeAndFlush(Unpooled.copiedBuffer("333",CharsetUtil.UTF_8));
                }catch(Exception e){
                    System.out.println("发生异常："+ e.getMessage());
                }
            }
        },5, TimeUnit.SECONDS);

        //将msg转成Bytebuf
        ByteBuf buf = (ByteBuf) msg;

        System.out.println("服务端接收到的消息为："+buf.toString(CharsetUtil.UTF_8)+" 222");

        //获取客户端地址
        System.out.println(ctx.channel().remoteAddress());

    }

    /**
     * 数据读取完毕的方法
     * 这里给客户端返回一个消息
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

        //writeAndFlush 将数据写入缓存，并刷新到Channe
        //一般要对发送到数据进行编码


        ctx.writeAndFlush(Unpooled.copiedBuffer("Hello 客户端",CharsetUtil.UTF_8));
        System.out.println("给客户端返回响应完毕");
    }

    /**
     * 异常处理的方法，一般需要关闭通道
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}


